#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>

#include "event_handle.h"
#include "net.h"

#define MAX_EVENTS   1024
#define BUFFER_SIZE  4096
#define THREAD_COUNT 1

typedef struct {
    int thread_id;
    const char *ip;
    int port;
} thread_param_t;

void on_new_connection(int client_sock, void *data)
{
    event_add((struct event_loop *)data, client_sock, EVENT_EPOLLIN);
}

void handle_session_stop()
{

}

/* rxbuf not empty */
void *on_data_in(struct event_handle *handle)
{
    if (handle->sess_type == SESSION_TYPE_SERVER) {
        net_accept_sock(handle->sock, on_new_connection, handle->loop);
        return NULL;
    }

    if (handle->sess_type == SESSION_TYPE_CLIENT) {
        return NULL;
    }

    if (handle->sess_type == SESSION_TYPE_PROXY) {
        return NULL;
    }

    return NULL;
}

/* txbuf not full */
void *on_data_out(struct event_handle *handle)
{
    return NULL;
}

/******************************************************************************
 * worker_thread -
 *******************************************************************************/
void *worker_thread(void *arg)
{
    thread_param_t *param = (thread_param_t *)arg;
    int thread_id = param->thread_id;
    const char *ip = param->ip;
    int port = param->port;

    int listen_fd = net_listen_sock(ip, port);
    if (listen_fd < 0) {
        fprintf(stderr, "Thread %d: Failed to create listen socket\n", thread_id);
        pthread_exit(NULL);
    }

    struct event_loop loop = { 0 };
    loop.on_event_epollin = on_data_in;
    loop.on_event_epollout = on_data_out;
    event_loop_init(&loop);

    struct event_handle *handle;
    handle = event_add(&loop, listen_fd, EVENT_EPOLLIN);
    if (handle == NULL)
        goto error;
    handle->data = NULL;

    event_loop_run(&loop);

error:
    pthread_exit(NULL);
    return NULL;
}

int main(int argc, char *argv[])
{
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <IP> <PORT>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    const char *ip = argv[1];
    int port = atoi(argv[2]);
    pthread_t threads[THREAD_COUNT];
    thread_param_t thread_params[THREAD_COUNT];
    int i;

    // create threads
    for (i = 0; i < THREAD_COUNT; i++) {
        thread_params[i].thread_id = i;
        thread_params[i].ip = ip;
        thread_params[i].port = port;

        if (pthread_create(&threads[i], NULL, worker_thread, &thread_params[i]) != 0) {
            perror("pthread_create");
            exit(EXIT_FAILURE);
        }
    }

    printf("Server started on %s:%d with %d threads\n", ip, port, THREAD_COUNT);

    for (i = 0; i < THREAD_COUNT; i++) {
        pthread_join(threads[i], NULL);
    }

    return 0;
}
